﻿using System;
using System.Web;
using System.Web.Mvc;
using AcademicPlanner.Framework.Helpers;
using AcademicPlanner.Framework.Libraries.Mvc;
using AcademicPlanner.Framework.Libraries.Validation;
using AcademicPlanner.Domain;
using AcademicPlanner.Domain.Models;
using AcademicPlanner.Presentation.Views.People;

namespace AcademicPlanner.Presentation.Controllers
{
	/// <summary>
	/// PeopleController is the MVC controller class for requests that are related to managing
	/// people in the AcademicPlanner application.
	/// </summary>
	/// <version>1.0</version>
	/// <since>1.0</since>
	[HandleError]
	public class PeopleController : Controller
	{
		/// <summary>
		/// Processes a request to sign someone up.
		/// This MVC action method forwards the request to the <c>MembershipMngr</c> of the
		/// domain layer of the AcademicPlanner application and handles errors that are not
		/// critical by storing status messages in the session and adding a summary of
		/// input errors if any to the json data object.
		/// </summary>
		/// <returns>The data to be returned to the browser as json.</returns>
		/// <seealso cref="P:AcademicPlanner.Presentation.AcademicPlannerWebApp.DomainMaster"/>
		/// <seealso cref="P:AcademicPlanner.Domain.DomainMaster.Membership"/>
		/// <seealso cref="M:AcademicPlanner.Domain.Components.MembershipMngr.performRegisterTask"/>
		/// <seealso cref="M:AcademicPlanner.Framework.Helpers.SessionHelper.AddSuccessStatusMessage"/>
		/// <seealso cref="M:AcademicPlanner.Framework.Helpers.SessionHelper.AddInfoStatusMessage"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		[AcceptVerbs(HttpVerbs.Post)]
		[AjaxOnly]
		public JsonResult Signup()
		{
			JsonResultData vResult = new JsonResultData();
			
			Post.NamesPrefix = "";
			var vEmail = Post.GetAsString("Email");

			try
			{
				Application.DomainMaster.Membership
					.performRegisterTask(vEmail, Server.UrlDecode(Url.Action("CompleteRegistration",
																				"People", 
																				new { pFromEmail = "{0}", 
																						pToken = "{1}", 
																						pPersonId = "{2}" })));
				SessionHelper.AddSuccessStatusMessage(string.Format(Tr("Congratulations! We successfuly " +
					"recorded your request to register. An email has been sent out to your inbox at {0}. " +
					"Please follow the instructions in the email to complete your registration."), vEmail));
				vResult.reload = true;
			}
			catch (InvalidModelPropertiesException vIx)
			{
				vResult.errors = Form.SummarizeErrors(vIx.Errors);
			}
			/*catch (NotAuthorizedOperationException vNox)
			{
				SessionHelper.AddInfoStatusMessage(Tr(vNox.Message));
				vResult.reload = true;
			}*/
			catch (NotCriticalDomainException vNcx)
			{
				SessionHelper.AddInfoStatusMessage(Tr(vNcx.Message));
				vResult.reload = true;
			}
			// TODO: HANDLE CRITICALDOMAINEXCEPTIONS IN 500 ERROR HANDLER
			catch (CriticalDomainException vCx)
			{
				SessionHelper.AddInfoStatusMessage(string.Format("{0} {1}", 
					Tr("A critical error occured while trying to sign you up! Please try again later."), 
					vCx.Message));
				vResult.reload = true;
			}

			return Json(vResult);
		}

		/// <summary>
		/// Processes a request to set a <c>Person</c> up (i.e. complete the registration process).
		/// This MVC action method forwards the request to the <c>MembershipMngr</c> of the
		/// domain layer of the AcademicPlanner application and handles errors that are not
		/// critical by storing status messages in the session and adding a summary of
		/// input errors if any to the json data object.
		/// </summary>
		/// <param name="pPersonId">The id of the <c>Person</c> to set up.</param>
		/// <returns>The data to be returned to the browser as json.</returns>
		/// <seealso cref="P:AcademicPlanner.Presentation.AcademicPlannerWebApp.DomainMaster"/>
		/// <seealso cref="P:AcademicPlanner.Domain.DomainMaster.Membership"/>
		/// <seealso cref="M:AcademicPlanner.Domain.Components.MembershipMngr.performSetupPersonTask"/>
		/// <seealso cref="M:AcademicPlanner.Framework.Helpers.SessionHelper.AddSuccessStatusMessage"/>
		/// <seealso cref="M:AcademicPlanner.Framework.Helpers.SessionHelper.AddInfoStatusMessage"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		[AcceptVerbs(HttpVerbs.Post)]
		[AjaxOnly]
		public JsonResult Setup(int pPersonId)
		{
			JsonResultData vResult = new JsonResultData();

			Post.NamesPrefix = "";
			var vSub = Post.AddSubFormSubmission("Account");

			var vName = Post.GetAsString("Name");
			var vUsername = vSub.GetAsString("UserName", "User");
			var vPassword = vSub.GetAsString("Password", "User");
			var vConfirmPassword = vSub.GetAsString("RepeatedPassword", "User");
			var vToken = (string)SessionHelper.Get("Presentation.PeopleController.SetupToken") ?? "";
			var vEmail = (string)SessionHelper.Get("Presentation.PeopleController.SetupEmail") ?? "";

			try
			{
				if (!StringValidator.IsIdenticalTo(vConfirmPassword, vPassword))
				{
					vResult.errors = Form.SummarizeError(string.Format(Tr("{0} must be the same as {1}."),
																		Labels.Get("RepeatedPassword", "User"),
																		Labels.Get("Password", "User")));
				}
				else
				{
					Application.DomainMaster.Membership
						.performSetupPersonTask(vToken, pPersonId, vEmail, vName, vUsername, vPassword);

					SessionHelper.AddSuccessStatusMessage(string.Format(Tr("Congratulations! You successfuly " +
						"completed your registration. You can now login and begin to use our service.")));
					vResult.redirect = Url.Action("Default", "Site");

					SessionHelper.Reset("Presentation.PeopleController.SetupToken", null);
					SessionHelper.Reset("Presentation.PeopleController.SetupEmail", null);
				}
			}
			catch (InvalidModelPropertiesException vIx)
			{
				vResult.errors = Form.SummarizeErrors(vIx.Errors);
			}
			catch (NotCriticalDomainException vNcx)
			{
				SessionHelper.AddInfoStatusMessage(Tr(vNcx.Message));
				vResult.reload = true;
			}

			return Json(vResult);
		}

		/// <summary>
		/// Displays the page to complete the registration process of a <c>Person</c>.
		/// This MVC action method returns the "Setup" view in a "InNoSection" master page.
		/// </summary>
		/// <param name="pFromEmail">The email of the <c>Person</c>.</param>
		/// <param name="pToken">The authentication token associated with the <c>Person</c>.</param>
		/// <param name="pPersonId">The id of the <c>Person</c>.</param>
		/// <returns>The view representation of the complete registration page.</returns>
		/// <seealso cref="P:AcademicPlanner.Presentation.AcademicPlannerWebApp.DomainMaster"/>
		/// <seealso cref="P:AcademicPlanner.Domain.DomainMaster.Membership"/>
		/// <seealso cref="M:AcademicPlanner.Domain.Components.MembershipMngr.GetPersonToSetup"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		[AcceptVerbs(HttpVerbs.Get)]
		public ViewResult CompleteRegistration(string pFromEmail, string pToken, int pPersonId)
		{
			var vViewModel = new SetupPersonViewModel();

			SessionHelper.Reset("Presentation.PeopleController.SetupToken", pToken);
			SessionHelper.Reset("Presentation.PeopleController.SetupEmail", pFromEmail);
			vViewModel.Person = Application.DomainMaster.Membership.GetPersonToSetup(pToken, pPersonId, pFromEmail);

			return View("Setup", "InNoSection", vViewModel);
		}
	}
}
